package org.nViron.nvRender;

//~--- non-JDK imports --------------------------------------------------------

import org.nViron.nvData.nvDataEntity;
import org.nViron.nvOrganic.nvLeaf;
import org.nViron.nvOrganic.nvNode;
import org.nViron.nvOrganic.nvOrganic;
import org.nViron.nvOrganic.nvRoot;
import org.nViron.nvOrganic.nvStalk;
import org.nViron.nvOrganic.nvStem;
import org.nViron.nvPlaces.nvPlace;
import org.nViron.nvSim.nvSimulator;
import org.nViron.nvTraces.nvTrace;

/**
 * Base class for all renderers. Projections, 3d space handling, culling e.g. is all done already. What you have to implement is the actual rendering of the different objects
 * @author Roland Haring <p>
 * <script type="text/javascript" src="http://www.ohloh.net/p/376434/widgets/project_basic_stats.js"></script>
 */
public abstract class nvRenderer {
    protected nvFrustum   frustum;
    protected boolean     renderDebugInfo;
    protected boolean     renderGrid;
    protected boolean     renderInfo;
    protected nvSimulator simulator;

    public nvRenderer(nvSimulator _sim) {
        simulator = _sim;
        setRenderGrid(false);
        setRenderDebugInfo(false);
    }

    abstract protected nvFrustum createFrustum();

    public final nvFrustum getFrustum() {
        return frustum;
    }

    abstract protected int getNumRenderPasses();

    public final nvSimulator getSimulator() {
        return simulator;
    }

    public void init() {
        frustum = createFrustum();
        frustum.setNearP(simulator.getProjection().geoToVizApprox(simulator.getConfig().getNearP()));
        frustum.setFarP(simulator.getProjection().geoToVizApprox(simulator.getConfig().getFarP()));
        frustum.setFOV(simulator.getConfig().getFOV());
    }

    public final boolean isRenderDebugInfo() {
        return renderDebugInfo;
    }

    public final boolean isRenderGrid() {
        return renderGrid;
    }

    public final boolean isRenderInfo() {
        return renderInfo;
    }

    abstract protected void onPostRenderScene(int renderpass);

    abstract protected void onPreRenderScene(int renderpass);

    abstract public void onReshape(int x, int y, int width, int height);

    abstract public void postRenderOrganic(nvOrganic organic);

    public void render() {
        setupCamera();
        renderBackground();
        renderMap();

        if (isRenderGrid()) {
            renderGrid();
        }

        for (int i = 0; i < getNumRenderPasses(); i++) {
            renderScene(i);
        }

        renderForeground();
    }

    abstract protected void renderBackground();

    abstract public void renderDataEntity(nvDataEntity entity);

    abstract protected void renderForeground();

    abstract protected void renderGrid();

    abstract public void renderLeaf(nvLeaf leaf);

    abstract protected void renderMap();

    abstract public void renderNode(nvNode node);

    abstract public void renderOrganic(nvOrganic organic);

    abstract public void renderPlace(nvPlace place);

    abstract public void renderRoot(nvRoot root);

    protected void renderScene(int renderpass) {
        onPreRenderScene(renderpass);
        simulator.render(this);
        onPostRenderScene(renderpass);
    }

    abstract public void renderStalk(nvStalk stalk);

    abstract public void renderStem(nvStem stem);

    abstract public void renderTrace(nvTrace trace);

    public final void setRenderDebugInfo(boolean renderDebugInfo) {
        this.renderDebugInfo = renderDebugInfo;
    }

    public final void setRenderGrid(boolean renderGrid) {
        this.renderGrid = renderGrid;
    }

    public final void setRenderInfo(boolean renderInfo) {
        this.renderInfo = renderInfo;
    }

    abstract protected void setupCamera();
}



